package com.benzhitech.tcp;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

/**
 * TCP 客户端示例
 * 用于测试与服务器的连接
 */
public class TcpClient {

    private static final Logger log = LoggerFactory.getLogger(TcpClient.class);
    
    private final String host;
    private final int port;
    private Channel channel;
    private EventLoopGroup group;
    
    /**
     * 创建 TCP 客户端
     * 
     * @param host 服务器主机
     * @param port 服务器端口
     */
    public TcpClient(String host, int port) {
        this.host = host;
        this.port = port;
    }
    
    /**
     * 连接到服务器
     * 
     * @return 是否连接成功
     */
    public boolean connect() {
        // 创建事件循环组
        group = new NioEventLoopGroup();
        
        try {
            // 创建客户端启动器
            Bootstrap b = new Bootstrap();
            b.group(group)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new TcpClientHandler());
                    }
                });
                
            // 连接服务器
            log.info("正在连接到服务器 {}:{}", host, port);
            ChannelFuture f = b.connect(host, port).sync();
            
            if (f.isSuccess()) {
                channel = f.channel();
                log.info("已连接到服务器: {}", channel.remoteAddress());
                return true;
            } else {
                log.error("连接服务器失败");
                return false;
            }
        } catch (Exception e) {
            log.error("连接服务器时发生异常", e);
            disconnect();
            return false;
        }
    }
    
    /**
     * 断开连接
     */
    public void disconnect() {
        if (channel != null) {
            channel.close();
            channel = null;
        }
        
        if (group != null) {
            group.shutdownGracefully();
            group = null;
        }
        
        log.info("已断开与服务器的连接");
    }
    
    /**
     * 发送消息到服务器
     * 
     * @param message 消息内容
     * @return 是否发送成功
     */
    public boolean sendMessage(String message) {
        if (channel != null && channel.isActive()) {
            ByteBuf buf = Unpooled.copiedBuffer(message, StandardCharsets.UTF_8);
            channel.writeAndFlush(buf);
            log.info("消息已发送: {}", message);
            return true;
        } else {
            log.warn("无法发送消息，连接未建立或已断开");
            return false;
        }
    }
    
    /**
     * 内部处理器类，处理来自服务器的消息
     */
    private static class TcpClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
        
        @Override
        public void channelActive(ChannelHandlerContext ctx) {
            log.info("与服务器的连接已建立");
        }
        
        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            log.info("与服务器的连接已断开");
        }
        
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
            byte[] bytes = new byte[msg.readableBytes()];
            msg.readBytes(bytes);
            String message = new String(bytes, StandardCharsets.UTF_8);
            log.info("收到服务器消息: {}", message);
        }
        
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            log.error("连接异常", cause);
            ctx.close();
        }
    }
    
    /**
     * 主方法，启动客户端并进行测试
     */
    public static void main(String[] args) {
        // 默认连接本地服务器
        String host = "localhost";
        int port = 9090;
        
        // 允许通过命令行参数指定服务器地址和端口
        if (args.length >= 1) {
            host = args[0];
        }
        if (args.length >= 2) {
            try {
                port = Integer.parseInt(args[1]);
            } catch (NumberFormatException e) {
                log.warn("无效的端口号: {}, 使用默认端口 9090", args[1]);
            }
        }
        
        TcpClient client = new TcpClient(host, port);
        
        // 连接服务器
        if (!client.connect()) {
            log.error("无法连接到服务器，程序退出");
            return;
        }
        
        // 发送第一条消息
        client.sendMessage("Hello from Tiny TCP Client!");
        
        // 启动交互式命令循环
        Scanner scanner = new Scanner(System.in);
        System.out.println("\n--- TCP 客户端交互控制台 ---");
        System.out.println("输入消息发送到服务器，输入 'exit' 退出");
        
        String input;
        boolean running = true;
        
        while (running) {
            System.out.print("> ");
            input = scanner.nextLine().trim();
            
            switch (input.toLowerCase()) {
                case "exit":
                case "quit":
                    running = false;
                    break;
                case "":
                    // 忽略空行
                    break;
                default:
                    client.sendMessage(input);
                    // 等待一段时间，以便接收响应
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
            }
        }
        
        // 断开连接并退出
        client.disconnect();
        scanner.close();
        System.out.println("已断开连接，程序退出");
    }
} 